package com.rock.platform.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.beanutils.BeanUtils;

import com.rock.platform.exception.BaseException;
import com.rock.platform.util.JsonUtils;

public class EntityUtil
{
    /**
     * 禁止实例化
     */
    private EntityUtil()
    {
    }
    /**
     * 获取查询条件实体
     * 
     * @param <T>
     * @param jsonString
     *            为空时返回空的实体
     * @param c
     * @return
     */
    public static <T> T getFilter(String jsonString, Class<T> c)
    {
        if (jsonString == null || jsonString.equals(""))
        {
            try
            {
                return c.newInstance();
            }
            catch (InstantiationException e)
            {
                throw new BaseException("不能实例化该类，InstantiationException异常");
            }
            catch (IllegalAccessException e)
            {
                throw new BaseException("不能实例化该类，IllegalAccessException异常");
            }
        }
        else
        {
            return JsonUtils.getEntity(jsonString, c);
        }
    }
    
    /**
     * 将实体属性值放入Map中
     * 
     * @param <T>
     * @param entity
     * @param update
     * @return
     */
    /*public static <T> HashMap<String, Object> entityToHashMap(T entity, OperateType update)
    {
        HashMap<String, Object> keyToValue = new HashMap<String, Object>();
        Class<?> classType = entity.getClass();
        Field fields[] = classType.getDeclaredFields();
        for (Field field : fields)
        {
            String key = null;
            Object value = null;
            Column c = field.getAnnotation(Column.class);
            Transient t = field.getAnnotation(Transient.class);

            if (t != null) continue;
            if (update.equals(OperateType.INSERT)) if (c != null && !c.insertable()) continue;
            if (update.equals(OperateType.UPDATE)) if (c != null && !c.updatable()) continue;

            try
            {
                if (c != null && !isNullOrEmpty(c.name()))
                    key = c.name();
                else
                    key = field.getName();
                value = BeanUtils.getProperty(entity, field.getName());
            }
            catch (Exception ex)
            {
                throw new BaseException(ex);
            }

            keyToValue.put(key, value);
        }
        return keyToValue;
    }*/
    
    public static <T> Map<String, Object> buildUpdateSql(T entity)
    {
        //String strSql = "";
        StringBuffer sbSql = new StringBuffer();
        String keyName = "";
        String keyDbName = "";
        String keyValue = "";
        
        Class<?> cls = entity.getClass();
        
        List<String> values = new ArrayList<String>();
        List<Object> keys = new ArrayList<Object>();
        
        List<Field> lFileds = new ArrayList<Field>();
        lFileds.addAll(Arrays.asList(cls.getSuperclass().getDeclaredFields()));
        lFileds.addAll(Arrays.asList(cls.getDeclaredFields()));
        /*
        Map<String,AttributeOverride> mAttr = new HashMap<String,AttributeOverride>();
        AttributeOverrides atts = cls.getAnnotation(AttributeOverrides.class);
        if (atts != null)
        {
            AttributeOverride att[] = atts.value();
            for (int i = 0; i < att.length; i++)
            {
                AttributeOverride a = att[i];
                mAttr.put(a.name(), a);
            }
        }*/
        
        boolean isID = false;
        for(Field f : lFileds)
        {
            isID = false;
            String value = null;
            String name = f.getName();

            if (name.equals("serialVersionUID")) continue;
            if (f.getAnnotation(Transient.class) != null) continue;
            
            if (f.getAnnotation(Id.class) != null)
            {
                keyName = name; 
                keyDbName = name;
                isID = true;
            }
            
            Column c = f.getAnnotation(Column.class);
            if (c != null)
            {
                if (!c.updatable()) continue;
                if (f.getAnnotation(Id.class) != null && c.name() != null)
                {
                    keyDbName = c.name();
                }
            }
            
            /*
            if (mAttr.containsKey(f.getName()))
            {
                AttributeOverride att = mAttr.get(f.getName());
                Column cc = att.column();
                if (!cc.updatable()) continue;
                name = cc.name();
                
                if (isID) keyDbName = name;
            }*/
            
            try
            {
                value = BeanUtils.getProperty(entity, f.getName());
                if (f.getName().equals(keyName))
                {
                    keyValue = value;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

            String strFieldValuePara = ":" + name + "Value";

            if (!isID)
            {
	            sbSql.append(name);
	            sbSql.append(" = ");
	            sbSql.append(strFieldValuePara);
	            sbSql.append(" , ");
	            
	            keys.add(name);
	            values.add(value);
            }
            //strSql += name + " = " + strFieldValuePara + ",";
        }
        
        sbSql.delete(sbSql.length()-2, sbSql.length());
        
        sbSql.insert(0, " set "  );
        sbSql.insert(0, cls.getAnnotation(Table.class).name());
        sbSql.insert(0, " update " );
        sbSql.append(" where ");
        sbSql.append(keyDbName);
        sbSql.append(" = :keyValue ");
        
        /*strSql = " update " + cls.getAnnotation(Table.class).name() 
               + " set " + strSql.substring(0, strSql.length() - 1)
               + " where " + keyDbName + " = :keyValue ";*/

        Map<String, Object> paras = new HashMap<String, Object>();
        for (int j = 0; j < values.size(); j++)
        {
            Object value = values.get(j);
            String key = keys.get(j) + "Value";
            paras.put(key, value);
        }
        paras.put("keyValue", keyValue);

        Map<String,Object> sqlMap = new HashMap<String,Object>();
        sqlMap.put("sql", sbSql.toString());
        sqlMap.put("paras", paras);
        return sqlMap;
    }
    
    public static <T> String getDbFileName(Class<T> cls, String filedName)
    {
        String name = "";
        
        List<Field> lFileds = new ArrayList<Field>();
        lFileds.addAll(Arrays.asList(cls.getSuperclass().getDeclaredFields()));
        lFileds.addAll(Arrays.asList(cls.getDeclaredFields()));
        
        Map<String,AttributeOverride> mAttr = new HashMap<String,AttributeOverride>();
        AttributeOverrides atts = cls.getAnnotation(AttributeOverrides.class);
        if (atts != null)
        {
            AttributeOverride att[] = atts.value();
            for (int i = 0; i < att.length; i++)
            {
                AttributeOverride a = att[i];
                if (!isNullOrEmpty(a.name())) mAttr.put(a.name(), a); 
            }
        }
        
        for(Field f : lFileds)
        {
            name = "";
            if (filedName.equalsIgnoreCase(f.getName()))
            {
                Column c = f.getAnnotation(Column.class);
                if (c != null)
                {
                    if (!isNullOrEmpty(c.name())) name = c.name();
                }
                
                if (mAttr.containsKey(f.getName()))
                {
                    AttributeOverride att = mAttr.get(f.getName());
                    Column cc = att.column();
                    if (cc != null)
                    {
                        if (!isNullOrEmpty(cc.name())) name = cc.name();
                    }
                }
                
                if (isNullOrEmpty(name)) name = f.getName();
                break;
            }            
        }
        return name;
    }
    
    /***
     * 验证变量值是否为空或者NULL
     * 
     * @param value
     * @return 返回true表示为空或者NULL
     */
    public static <T> Boolean isNullOrEmpty(T value)
    {
        if (value == null)
        {
            return true;
        }
        if (value instanceof String)
        {
            if ("".equals(((String) value).trim())) return true;
        }
        if (value instanceof Map<?, ?>)
        {
            if (((Map<?, ?>) value).isEmpty()) return true;
        }

        return false;
    }

/*    *//**
     * 根据bean id取得bean的实例
     * 
     * @param strBeanID
     * @return
     *//*
    public static Object getBean(String strBeanID)
    {
        ServletContext sc = ServletActionContext.getServletContext();
        if (sc == null) // 单元测试的特殊处理
        {
            return SpringContextUtil.getBean(strBeanID);
        }
        else
        {
            WebApplicationContext wac = WebApplicationContextUtils
                    .getRequiredWebApplicationContext(sc);
            return wac.getBean(strBeanID);
        }
    }
*/
}
